/******************************************************************************* 
 * Copyright (C) 2012-2015 Microfountain Technology, Inc. All Rights Reserved. 
 * 
 * Unauthorized copying of this file, via any medium is strictly prohibited.   
 * Proprietary and confidential
 * 
 * Last Modified: 2015-9-22 17:07:12
 ******************************************************************************/
package cn.cmcc.online.smsapi.sdk.db.bizport;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.LineNumberReader;
import java.util.Hashtable;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import cn.cmcc.online.smsapi.sdk.constant.Constant;
import cn.cmcc.online.smsapi.sdk.db.ParseItemManager;
import cn.cmcc.online.smsapi.sdk.db.ParsePhonePubIdManager;
import cn.cmcc.online.smsapi.sdk.db.XyCursor;
import cn.cmcc.online.smsapi.sdk.log.LogManager;
import cn.cmcc.online.smsapi.sdk.threadpool.SmartSmsThreadPoolManager;
import cn.cmcc.online.smsapi.sdk.util.FileUtils;
import cn.cmcc.online.smsapi.sdk.util.StringUtils;

public class BizportDBManager {
    private static final String dataBaseName = "bizport.db";
    /*SDK-627 hewengao/20160929 start*/
    static final int dataBaseVersion = 6;
    /*SDK-627 hewengao/20160929 end*/
    static MyDbHelper dbHelper = null;
    static int timeOut = 1000;
    static int sleepTime = 100;
    public static Object dblock = new Object();
    static Hashtable<SQLiteDatabase, Integer> listDB = new Hashtable<SQLiteDatabase, Integer>();

    private static SQLiteDatabase createSQLiteDatabase(Context contexts) {

        synchronized (listDB) {
            if (listDB.size() >= 10) {
                return null;
            }
            MyDbHelper helper = getHelper(contexts.getApplicationContext());
            SQLiteDatabase db = helper.getReadableDatabase();
            Integer cnt = null;
            if (db != null) {
                cnt = listDB.get(db);
                if (cnt == null) {
                    cnt = 1;
                } else {
                    cnt++;
                }
                listDB.put(db, cnt);
                if (!db.isOpen()) {
                    LogManager.d("duoqu_bizport", "is not open.");
                    listDB.remove(db);
                    return null;
                }
            }
            return db;
        }
    }
    /*SDK-630 hewengao/20161002 start*/
    public synchronized static void close(SQLiteDatabase db) {
    /*SDK-630 hewengao/20161002 end*/
        try {
            if (db == null) {
                LogManager.d("duoqu_bizport", "$$$$$ db close is null");
                return;
            }
            synchronized (listDB) {
                Integer cnt = listDB.get(db);
                // LogManager.d("duoqu_bizport", "$$$$$ db close : " + cnt);
                if (cnt == null) {
                    LogManager.d("duoqu_bizport", "$$$$$ db close cnt is null "
                            + db.hashCode());
                    // 这种情况如果发生就是有问题的
                    // db.close();
                } else {
                    cnt = cnt - 1;
                    if (cnt == 0) {
                        listDB.remove(db);
                        db.close();
                        // LogManager.e("duoqu_bizport", "$$$$$ db close : "+
                        // cnt);
                    } else {
                        listDB.put(db, cnt);
                    }
                }
            }
            if (listDB.size() == 0) {
                LogManager.d("duoqu_bizport",
                        "%%%%%%%%%% db close listDB size is 0");
                if (dbHelper != null) {
                    dbHelper.close();
                }
                // System.gc();
            }
        } catch (Throwable e) {
            // e.printStackTrace();
            LogManager
                    .d("xiaoyaun", "BizportDBManager close " + e.getMessage());
        }

    }
    /*SDK-630 hewengao/20161002 start*/
    public synchronized  static SQLiteDatabase getSQLiteDatabase() {
    /*SDK-630 hewengao/20161002 end*/
        SQLiteDatabase sb = null;
        long start = System.currentTimeMillis();
        long end = 0;
        while (sb == null) {

            sb = createSQLiteDatabase(Constant.getContext());
            if (sb != null) {
                return sb;
            }
            end = System.currentTimeMillis();
            end = (end - start);
            if (end >= timeOut) {
                break;
            }
            try {
                Thread.sleep(sleepTime);
            } catch (InterruptedException e) {
                // e.printStackTrace();
                LogManager.w("xiaoyaun", "BizportDBManager getSQLiteDatabase ",e);
            }
        }
        return sb;
    }

    private synchronized static MyDbHelper getHelper(Context contexts) {

        if (dbHelper == null) {
            dbHelper = new MyDbHelper(contexts, dataBaseName, null,
                    dataBaseVersion);
        }
        return dbHelper;
    }

    private static class MyDbHelper extends SQLiteOpenHelper {
        public MyDbHelper(Context contexts, String name, CursorFactory factory,
                int version) {
            super(contexts, name, factory, version);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {

            try {
                createDb(db);
            } catch (Throwable e) {
//                e.printStackTrace();
                /*SDK-550 hewengao 20160719 start*/
	             LogManager.e(Constant.TAG, "onCreate: ", e);
	             /*SDK-550 hewengao 20160719 end*/
            }
        }

        @Override
        public void onOpen(SQLiteDatabase db) {
            super.onOpen(db);
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            createDb(db);
        }

        @Override
        public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            try {
                db.execSQL(ParseItemManager.DROP_TABLE);
                db.execSQL(ParsePhonePubIdManager.DROP_TABLE);               
            } catch (Throwable e) {
                /*SDK-550 hewengao 20160719 start*/
                LogManager.w("xiaoyaun", "BizportDBManager onDowngrade", e);
                /*SDK-550 hewengao 20160719 end*/
            }
            createDb(db);
        }
    }

    private static void createDb(SQLiteDatabase SQLiteDatabase) {
        try {
            SQLiteDatabase.execSQL(ParseItemManager.CREATE_TABLE);
            SQLiteDatabase.execSQL(ParseItemManager.CREATE_INDEX);
            /*SDK-627 hewengao/20160929 start*/
            SQLiteDatabase.execSQL(ParseItemManager.CREATE_INDEX_SID);
            /*SDK-627 hewengao/20160929 end*/
            SQLiteDatabase.execSQL(ParsePhonePubIdManager.CREATE_PUB_TABLE);
            /*SDK-627 hewengao/20160929 start*/
            SQLiteDatabase.execSQL(ParsePhonePubIdManager.CREATE_INDEX_PHONE);
            /*SDK-627 hewengao/20160929 end*/
            addColumn(SQLiteDatabase, ParseItemManager.ADD_LAST_USE_TIME);

        } catch (Throwable e) {
            // e.printStackTrace();
            /*SDK-550 hewengao 20160719 start*/
        	  LogManager.e(Constant.TAG, "createDb: ", e);
        	  /*SDK-550 hewengao 20160719 end*/
        }

    }
    
    private static void addColumn(SQLiteDatabase SQLiteDatabase, String sql) {
        try {
            SQLiteDatabase.execSQL(sql);
        } catch (Throwable e) {
        }
    }

    private static SQLiteDatabase getReadSQLiteDatabase() {
        return getSQLiteDatabase();
    }

    public static XyCursor query(String tableName, String[] columns,
            String selection, String[] selectionArgs) throws Exception {
        return query(false, tableName, columns, selection, selectionArgs, null,
                null, null, null);
    }

    public static XyCursor query(boolean distinct, String tableName,
            String[] columns, String selection, String[] selectionArgs,
            String groupBy, String having, String orderBy, String limit)
            throws Exception {

        XyCursor xyCursor = null;
        SQLiteDatabase mySQLiteDatabase = null;
        try {
            mySQLiteDatabase = getReadSQLiteDatabase();
            Cursor cursor = mySQLiteDatabase.query(distinct, tableName,
                    columns, selection, selectionArgs, groupBy, having,
                    orderBy, limit);
            xyCursor = new XyCursor(mySQLiteDatabase, cursor, 1);
        } catch (Throwable e) {
            close(mySQLiteDatabase);
        }
        return xyCursor;
    }

    public static XyCursor query(String tableName, String[] columns,
            String selection, String[] selectionArgs, String groupBy,
            String having, String orderBy, String limit) throws Exception {
        // initDbManager();
        XyCursor xyCursor = null;
        SQLiteDatabase mySQLiteDatabase = null;
        try {
            mySQLiteDatabase = getSQLiteDatabase();
            Cursor cursor = mySQLiteDatabase.query(tableName, columns,
                    selection, selectionArgs, groupBy, having, orderBy, limit);
            xyCursor = new XyCursor(mySQLiteDatabase, cursor, 1);
        } catch (Throwable e) {
            // e.printStackTrace();
            close(mySQLiteDatabase);
            /*SDK-550 hewengao 20160719 start*/
            LogManager.w("xiaoyaun","BizportDBManager 1query ",e);
            /*SDK-550 hewengao 20160719 end*/
        } finally {

        }
        return xyCursor;
    }

    public static XyCursor queryPatternString(SQLiteDatabase mySQLiteDatabase,
            boolean distinct, String tableName, String[] columns,
            String selection, String[] selectionArgs, String groupBy,
            String having, String orderBy, String limit, Context context)
            throws Exception {
        // initDbManager();
        XyCursor xyCursor = null;
        try {

            Cursor cursor = mySQLiteDatabase.query(distinct, tableName,
                    columns, selection, selectionArgs, groupBy, having,
                    orderBy, limit);
            xyCursor = new XyCursor(null, cursor, 1);
        } catch (Throwable e) {
            // e.printStackTrace();
            /*SDK-550 hewengao 20160719 start*/
            LogManager.e("xiaoyaun","BizportDBManager 2query ",e);
            /*SDK-550 hewengao 20160719 end*/
        }
        return xyCursor;
    }

    // cccccccccc
    public static int delete(String tableName, String whereClause,
            String[] whereArgs) throws Exception {
        // initDbManager();

        synchronized (dblock) {
            int res = -1;
            SQLiteDatabase mySQLiteDatabase = null;
            try {
                mySQLiteDatabase = getSQLiteDatabase();
                res = mySQLiteDatabase
                        .delete(tableName, whereClause, whereArgs);
                // LogManager.i("delete res:"+res);
            } catch (Throwable e) {
                res = -1;
            } finally {
                close(mySQLiteDatabase);
            }
            return res;
        }
    }

    public static int update(String tableName, ContentValues values,
            String whereClause, String[] whereArgs) throws Exception {
        synchronized (dblock) {
            int res = -1;
            SQLiteDatabase mySQLiteDatabase = null;
            try {
                mySQLiteDatabase = getSQLiteDatabase();
                res = mySQLiteDatabase.update(tableName, values, whereClause,
                        whereArgs);
            } catch (Throwable e) {
                res = -1;
            } finally {
                close(mySQLiteDatabase);
            }
            return res;
        }
    }

    public static long insert(String tableName, ContentValues values)
            throws Exception {
        synchronized (dblock) {
            long res = -1;
            SQLiteDatabase mySQLiteDatabase = null;
            try {
                mySQLiteDatabase = getSQLiteDatabase();
                res = mySQLiteDatabase.insert(tableName, null, values);
            } catch (Throwable e) {
                res = -1;
            } finally {
                close(mySQLiteDatabase);
            }
            return res;
        }
    }

    public static XyCursor rawQuery(String sql, String[] selectionArgs)
            throws Exception {
        // initDbManager();
        SQLiteDatabase mySQLiteDatabase = null;
        XyCursor xyCursor = null;

        try {
            mySQLiteDatabase = getSQLiteDatabase();
            Cursor cursor = mySQLiteDatabase.rawQuery(sql, selectionArgs);
            /* SDK-531 huangzhiqiang 20160711 start */
            xyCursor = new XyCursor(mySQLiteDatabase, cursor, 1);
            /* SDK-531 huangzhiqiang 20160711 end */
        } catch (Throwable e) {
            // e.printStackTrace();
            close(mySQLiteDatabase);
            /*SDK-550 hewengao 20160719 start*/
            LogManager.w("xiaoyaun","BizportDBManager rawQuery ",e);
            /*SDK-550 hewengao 20160719 end*/
        }
        return xyCursor;
    }

    public static void excSql(String filePath, boolean isDeleteFile)
            throws Exception {
        if (!FileUtils.isFileExists(filePath)) {
            return;
        }
        SQLiteDatabase db = null;
        BufferedReader bw = null;
        File file = null;
        java.io.LineNumberReader r = null;
        try {
            file = new File(filePath);
            bw = new BufferedReader(new FileReader(file));

            r = new LineNumberReader(bw);
            String line = null;
            db = getSQLiteDatabase();
            db.beginTransaction();

            try {
                int cnt = 0;
                while ((line = r.readLine()) != null) {
                    if (!StringUtils.isNull(line)) {
                        db.execSQL(line);// 执行每行的sql

                        cnt++;
                        if (cnt % 100 == 0) {
                            // LogManager.d("duoqu_test", " execSql: "+cnt);
                            // Thread.sleep(1);
                        }
                    }

                }
                r.close();

            } catch (Throwable e) {
                throw e;
            }
        } catch (Throwable e) {

//            e.printStackTrace();
            /*SDK-550 hewengao 20160719 start*/
	         LogManager.w(Constant.TAG, "excSql: ", e);
	        /*SDK-550 hewengao 20160719 start*/
        } finally {
            closeDB(filePath, isDeleteFile, r, bw, db);
        }

    }

    public static void closeDB(String filePath, boolean isDeleteFile,
            java.io.LineNumberReader r, BufferedReader bw, SQLiteDatabase db) {
        try {
            try {
                if (isDeleteFile) {
                    FileUtils.deleteAllFile(filePath);
                }
            } catch (Throwable e2) {
                // TODO: handle Throwable
            }

            try {
                if (r != null)
                    r.close();
            } catch (Throwable e2) {
                // TODO: handle Throwable
            }

            try {
                if (bw != null)
                    bw.close();
            } catch (Throwable e2) {
                // TODO: handle Throwable
            }

            if (db != null) {
                try {
                    if (db.inTransaction()) {
                        db.setTransactionSuccessful();
                        db.endTransaction();
                    }
                } catch (Throwable e) {
//                    e.printStackTrace();
                    /*SDK-550 hewengao 20160719 start*/
   	                 LogManager.w(Constant.TAG, "closeDB: ", e);
   	                /*SDK-550 hewengao 20160719 end*/
                } finally {
                    close(db);
                }
            }
        } catch (Throwable e) {
            // TODO: handle Throwable
            /*SDK-550 hewengao 20160719 start*/
            LogManager.w("xiaoyaun","BizportDBManager closeDB ",e);
            /*SDK-550 hewengao 20160719 end*/
        }
    }

    public static void closeCursor(Cursor cur) {
        if (cur != null) {
            cur.close();
        }
    }
    
   public static void execSQL(final String sql){
       if(StringUtils.isNull(sql)) return;
       /*SDK-616 hewengao 20160912 start*/
       SmartSmsThreadPoolManager.iccidPool.execute(new Runnable() {
       /*SDK-616 hewengao 20160912 end*/
			public void run() {
				try {		
		    		synchronized (BizportDBManager.dblock) {
		                SQLiteDatabase db = null;
		                try {
		                    db = BizportDBManager.getSQLiteDatabase();		                 
		                    db.execSQL(sql);
		                } catch (Throwable e) {
		                    /*SDK-550 hewengao 20160719 start*/
		                    LogManager.w(Constant.TAG, "execSQL: ", e);
		                    /*SDK-550 hewengao 20160719 end*/
		                } finally {
		                	BizportDBManager.close(db);
		                }
		            }
		    	
				} catch (Throwable e) {
		            LogManager.w(Constant.TAG, "execSQL: ", e);
				}
				  
				
			}
		});
   }
    /*SMARTISAN-129 songzhirong 20160819 start*/
    public static void deleteOldData(){
        try {
            BizportDBManager.delete(ParseItemManager.TABLE_NAME, null,null);
            BizportDBManager.delete(ParsePhonePubIdManager.TABLE_NAME, null,null);
        } catch (Throwable e) {
            LogManager.w("xiaoyaun","BizportDBManager deleteOldData ",e);
        }
    }
    /*SMARTISAN-129 songzhirong 20160819 end*/

}
